﻿using System;
using System.Diagnostics;
using System.ServiceModel;
using System.Threading;
using FitAutomation.ServiceRef;
using FitAutomation.Server;
using IFitAutomationHostService = FitAutomation.Server.IFitAutomationHostService;

namespace FitAutomation.Client
{
	class FitAutomationClient
	{
		DuplexChannelFactory<IFitAutomationHostService> _factory;

		IFitAutomationHostService _channel;

		InstanceContext _site;

		//FitAutomationHostServiceClient _client;

		readonly object _sync = new object();

		public void Connect()
		{
			lock (_sync)
			{
				for (int i = 0; i < 3; i++)
				{
					if (TryConnect())
					{
						break;
					}
					Thread.Sleep(300);
				}
				if (_channel == null)
				{
					throw _ex;
				}
			}
		}

		Exception _ex;

		//[DebuggerStepThrough]
		bool TryConnect()
		{
			try
			{
				if (_channel != null && _channel.GetHostProcessId() != 0)
				{
					return true;
				}

				if (_factory == null || _factory.State == CommunicationState.Faulted || _factory.State == CommunicationState.Closed)
				{
					_site = new InstanceContext(new FitAutomationHostServiceCallback());

					var binding = new WSDualHttpBinding()
					              	{
					              		OpenTimeout = TimeSpan.FromSeconds(2),
					              		CloseTimeout = TimeSpan.FromSeconds(2),
					              		ReceiveTimeout = TimeSpan.FromSeconds(2),
					              		SendTimeout = TimeSpan.FromSeconds(2),
					              	};

					binding.Security.Mode = WSDualHttpSecurityMode.None;

					_factory = new DuplexChannelFactory<IFitAutomationHostService>(_site, binding, Consts.Address);
				}

				_channel = _factory.CreateChannel();

				_channel.GetHostProcessId();


				return true;
			}
			catch(Exception ex)
			{
				_channel = null;
				if (_factory != null)
				{
					_factory.Abort();
				}
				if (_site != null)
				{
					_site.Close();
				}
				_site = null;
				_factory = null;
				_ex = ex;
				Process.Start(typeof (FitAutomationHost).Assembly.Location, "host");
				return false;
			}
		}

		public IFitAutomationHostService Channel
		{
			get
			{
				Connect();
				return _channel;
			}
		}
	}
}